package infra_domainservice

import (
	"errors"
	"fmt"
	"lzq-admin/base/domainconsts"
	"lzq-admin/base/domainservice"
	infra_model "lzq-admin/internal/infrastructure/model"
	"lzq-admin/pkg/cache"
	"lzq-admin/pkg/orm"
	"lzq-admin/pkg/utility"

	"github.com/gin-gonic/gin"
	jsoniter "github.com/json-iterator/go"
)

/**
 * @Author  糊涂的老知青
 * @Date    2022/7/5
 * @Version 1.0.0
 */

type SystemDictionaryDomainService struct {
	domainservice.BaseDomainService
}

func NewDSSystemDictionary(c *gin.Context) *SystemDictionaryDomainService {
	return &SystemDictionaryDomainService{
		domainservice.BaseDomainService{
			GinCtx: c,
		},
	}
}

func (s *SystemDictionaryDomainService) Insert(inputDto infra_model.CreateSystemDictionaryDto) (infra_model.SystemDictionary, error) {
	var entity infra_model.SystemDictionary
	lzqOrm := orm.NewLzqOrm(s.GinCtx)
	if isExist, err := lzqOrm.QSession(false).Where("DictCode = ? and DictKey = ?", inputDto.DictCode, inputDto.DictKey).Exist(&entity); err != nil {
		return entity, err
	} else if isExist {
		return entity, errors.New(fmt.Sprintf("该字典Key：%s已存在，请更换字典Key", inputDto.DictKey))
	}

	entity.ID = utility.UuidCreate()
	entity.DictCode = inputDto.DictCode
	entity.DictKey = inputDto.DictKey
	entity.DictValue = inputDto.DictValue
	entity.Remark = inputDto.Remark
	entity.Sort = inputDto.Sort
	entity.Status = domainconsts.CommonStatusEnable
	if _, err := lzqOrm.ISession().Insert(&entity); err != nil {
		return entity, err
	}

	cacheKey := cache.NewLzqCacheKey(s.GinCtx).GetLzqCacheTypeSystemDict(entity.DictCode)
	cacheObj := s.SystemDictToSimple(entity)
	fmt.Println(cacheKey, cacheObj)
	cache.RedisUtil.NewRedis(s.GinCtx, false).HSet(cacheKey, entity.DictKey, cacheObj, 0)
	return entity, nil
}

func (s *SystemDictionaryDomainService) Update(inputDto infra_model.UpdateSystemDictionaryDto) (infra_model.SystemDictionary, error) {
	var entity infra_model.SystemDictionary
	lzqOrm := orm.NewLzqOrm(s.GinCtx)
	if isExist, err := lzqOrm.QSession(false).ID(inputDto.ID).Get(&entity); err != nil {
		return entity, err
	} else if !isExist {
		return entity, errors.New("字典不存在")
	}

	entity.DictValue = inputDto.DictValue
	entity.Remark = inputDto.Remark
	entity.Sort = inputDto.Sort
	if _, err := lzqOrm.USession(false).AllCols().ID(entity.ID).Update(&entity); err != nil {
		return entity, err
	}
	s.UpdateSystemDictCache(entity)
	return entity, nil
}

func (s *SystemDictionaryDomainService) UpdateStatus(id string) error {
	var entity infra_model.SystemDictionary
	lzqOrm := orm.NewLzqOrm(s.GinCtx)
	if isExist, err := lzqOrm.QSession(false).ID(id).Get(&entity); err != nil {
		return err
	} else if !isExist {
		return errors.New("字典不存在")
	}
	if entity.Status == domainconsts.CommonStatusEnable {
		entity.Status = domainconsts.CommonStatusDisable
	} else {
		entity.Status = domainconsts.CommonStatusEnable
	}
	if _, err := lzqOrm.USession(false).Cols("Status").ID(id).Update(&entity); err != nil {
		return err
	}
	s.UpdateSystemDictCache(entity)
	return nil
}

func (s *SystemDictionaryDomainService) Delete(id string) error {
	var entity infra_model.SystemDictionary
	lzqOrm := orm.NewLzqOrm(s.GinCtx)
	if isExist, err := lzqOrm.QSession(false).ID(id).Get(&entity); err != nil {
		return err
	} else if !isExist {
		return errors.New("字典不存在")
	}

	if _, err := lzqOrm.DSession(false).ID(id).Update(&entity); err != nil {
		return err
	}

	cacheKey := cache.NewLzqCacheKey(s.GinCtx).GetLzqCacheTypeSystemDict(entity.DictCode)
	cache.RedisUtil.NewRedis(s.GinCtx, false).HDelete(cacheKey, entity.DictKey)
	return nil
}

func (s *SystemDictionaryDomainService) GetDictByDictKey(dictCode, dictKey string) (infra_model.SimpleSystemDictionaryDto, error) {
	var entity infra_model.SystemDictionary
	var result infra_model.SimpleSystemDictionaryDto

	cacheKey := cache.NewLzqCacheKey(s.GinCtx).GetLzqCacheTypeSystemDict(dictCode)
	cacheJson := cache.RedisUtil.NewRedis(s.GinCtx, false).HGet(cacheKey, dictKey)
	if cacheJson != "" {
		jsoniter.UnmarshalFromString(cacheJson, &result)
		return result, nil
	}

	if isExist, err := orm.NewLzqOrm(s.GinCtx).QSession(false).Where("DictCOde = ? and DictKey = ?", dictCode, dictKey).Get(&entity); err != nil {
		return result, err
	} else if !isExist {
		return result, errors.New(fmt.Sprintf("该字典：%s下不存在该Key：%s", dictCode, dictKey))
	}
	result = s.SystemDictToSimple(entity)
	cache.RedisUtil.NewRedis(s.GinCtx, false).HSet(cacheKey, dictKey, result, 0)

	return result, nil
}

func (s *SystemDictionaryDomainService) GetDictByDictCode(dictCode string) ([]infra_model.SimpleSystemDictionaryDto, error) {
	var list = make([]infra_model.SystemDictionary, 0)
	var result = make([]infra_model.SimpleSystemDictionaryDto, 0)

	cacheKey := cache.NewLzqCacheKey(s.GinCtx).GetLzqCacheTypeSystemDict(dictCode)
	cacheJson := cache.RedisUtil.NewRedis(s.GinCtx, false).HGetAll(cacheKey)
	if len(cacheJson) > 0 {
		for _, v := range cacheJson {
			var ssd infra_model.SimpleSystemDictionaryDto
		_:
			jsoniter.UnmarshalFromString(v, &ssd)
			result = append(result, ssd)
		}
		return result, nil
	}

	if err := orm.NewLzqOrm(s.GinCtx).QSession(false).Where("DictCode = ?", dictCode).Find(&list); err != nil {
		return result, err
	}
	for _, v := range list {
		m := s.SystemDictToSimple(v)
		result = append(result, m)
		cache.RedisUtil.NewRedis(s.GinCtx, false).HSet(cacheKey, v.DictKey, m, 0)
	}
	return result, nil
}

func (s *SystemDictionaryDomainService) SystemDictToSimple(v infra_model.SystemDictionary) infra_model.SimpleSystemDictionaryDto {
	return infra_model.SimpleSystemDictionaryDto{
		SystemDictionaryBase: infra_model.SystemDictionaryBase{
			DictCode:  v.DictCode,
			DictKey:   v.DictKey,
			DictValue: v.DictValue,
			Sort:      v.Sort,
			Remark:    v.Remark,
		},
		Status: v.Status,
	}
}

func (s *SystemDictionaryDomainService) UpdateSystemDictCache(v infra_model.SystemDictionary) {
	cacheKey := cache.NewLzqCacheKey(s.GinCtx).GetLzqCacheTypeSystemDict(v.DictCode)
	cacheObj := cache.RedisUtil.NewRedis(s.GinCtx, false).HGet(cacheKey, v.DictKey)
	if cacheObj != "" {
		cache.RedisUtil.NewRedis(s.GinCtx, false).HDelete(cacheKey, v.DictKey)
	}

	tt := s.SystemDictToSimple(v)
	cache.RedisUtil.NewRedis(s.GinCtx, false).HSet(cacheKey, v.DictKey, tt, 0)
}

func (s *SystemDictionaryDomainService) RefreshSystemDictCache() error {
	cache.RedisUtil.NewRedis(s.GinCtx, false).Delete(cache.LzqCacheHelper.GetCacheTypeVersionKey(cache.LzqCacheTypeSystemDict))
	return nil
}
